package com.bxl.chooser.server;


import com.bxl.chooser.context.ChooserContext;
import com.bxl.chooser.factory.HandlerAdapterFactory;
import com.bxl.netty.rpc.client.common.pool.ZoneClientPool;
import com.bxl.netty.rpc.common.Lifecycle;
import com.bxl.netty.rpc.common.serialize.KryoSerialize;
import com.bxl.netty.rpc.common.serialize.Serialize;
import com.bxl.netty.rpc.common.util.HandlerFactory;
import com.bxl.netty.rpc.register.server.common.server.Server;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * <>
 *
 * @author baixl
 * @date 2021/2/25
 */
public class ChooseServerContextImpl implements ChooseServerContext, Lifecycle {
    private Lifecycle server;
    private Serialize serialize;
    private ChooserContext chooserContext;
    private List<HandlerFactory> decoder;
    private List<HandlerFactory> encoder;
    private List<HandlerFactory> handler;

    private ZoneInfos zoneInfos;
    private SlidingWindow slidingWindow;

    private int port = 7777;

    public ChooseServerContextImpl(int port) {
        this.port = port;
    }

    /*public static void main(String[] args) {
        ChooseServerContextImpl context = new ChooseServerContextImpl();
        context.init().start();
    }*/

    public String getApp() {
        return "register";
    }

    public ChooseServerContextImpl init() {
        //序列化
        configSerialize();
        configDecoder();
        configEncoder();
        configHandler();
        //心跳统计信息
        slidingWindowInit();
        //注册信息
        zoneInfosInit();

        return this;
    }

    protected void slidingWindowInit() {
        //统计间隔-客户端配置的时候,要注意最大间隔.现在是不能大于30秒
        this.slidingWindow = new SlidingWindow(30, 1, TimeUnit.SECONDS);
        this.slidingWindow.init();
    }

    protected void configDecoder() {
        decoder = new ArrayList<HandlerFactory>();
        decoder.add(new HandlerAdapterFactory(ChooserServerMsgDecoder.class));
    }

    protected void configEncoder() {
        encoder = new ArrayList<HandlerFactory>();
        encoder.add(new HandlerFactory(ChooseServerMsgEncoder.class));
    }

    protected void configHandler() {
        handler = new ArrayList<HandlerFactory>();
        handler.add(new HandlerFactory(ChooseServerHandler.class));
    }

    protected void zoneInfosInit() {
        this.zoneInfos = new ZoneInfos(this, 30, TimeUnit.SECONDS);
    }

    public List<HandlerFactory> getHandler() {
        return this.handler;
    }

    public ZoneClientPool getClientPool() {
        return null;
    }

    /**
     * 可以修改为配置化
     */
    protected void configSerialize() {
        serialize = new KryoSerialize();
    }

    @Override
    public ChooserContext getChooserContext() {
        return this.chooserContext;
    }

    public void setChooserContext(ChooserContext chooserContext) {
        this.chooserContext = chooserContext;
    }

    public void start() {
        server = new Server(port, this, false);
        server.start();
    }

    public SlidingWindow getSlidingWindow() {
        return slidingWindow;
    }

    public void setSlidingWindow(SlidingWindow slidingWindow) {
        this.slidingWindow = slidingWindow;
    }

    public void stop() {
        server.stop();
        System.exit(1);
    }

    public Lifecycle getServer() {
        return server;
    }

    public void setServer(Lifecycle server) {
        this.server = server;
    }

    public int getPort() {
        return port;
    }

    public void setPort(int port) {
        this.port = port;
    }

    public Serialize getSerialize() {
        return serialize;
    }

    public void setSerialize(Serialize serialize) {
        this.serialize = serialize;
    }

    public List<HandlerFactory> getDecoder() {
        return decoder;
    }

    public void setDecoder(List<HandlerFactory> decoder) {
        this.decoder = decoder;
    }

    public List<HandlerFactory> getEncoder() {
        return encoder;
    }

    public void setEncoder(List<HandlerFactory> encoder) {
        this.encoder = encoder;
    }

    public ZoneInfos getZoneInfos() {
        return zoneInfos;
    }

    public void setZoneInfos(ZoneInfos zoneInfos) {
        this.zoneInfos = zoneInfos;
    }
}
